﻿//-----------------------------------------------------------------------
// <copyright file="ViewModelBase.cs" company="WpfDevelopment.com">
//     Copyright WpfDevelopment.com. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace WpfDevelopment.MVVM
{
    using System;
    using System.ComponentModel;
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization;
    using System.Linq.Expressions;
    using System.Diagnostics.Contracts;

    /// <summary>
    /// The base class for a view model entity
    /// </summary>
    public abstract class ViewModelBase : INotifyPropertyChanged
    {
        /// <summary>
        /// The culture manager, manages culture resources
        /// </summary>
        private ICultureManager cultureManager;

        /// <summary>
        /// The logger instance
        /// </summary>
        private ILog log = IoC.Container.GetInstanceOf<ILog>();

        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Gets the culture manager.
        /// </summary>
        /// <value>The culture manager.</value>
        public ICultureManager CultureManager
        {
            get
            {
                if (this.cultureManager == null)
                {
                    var communicationBus = IoC.Container.GetInstanceOf<ICommunicationBus>();
                    var resourceManager = IoC.Container.GetInstanceOf<IResourceManager>();
                    Contract.Assume(communicationBus != null);
                    Contract.Assume(resourceManager != null);
                    Contract.Assume(log != null);

                    this.cultureManager = new CultureManager(
                        this.GetType(), 
                        communicationBus, 
                        this.log, 
                        resourceManager);
                }

                return this.cultureManager;
            }
        }

        /// <summary>
        /// Notifies the system that the property is changed.
        /// </summary>
        /// <typeparam name="TProperty">The Property to Notify</typeparam>
        /// <param name="property">A lambda expression defining the property that changed.</param>
        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "Lambda"), 
         SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "Used to allow (() => PropertyName)")]
        protected void NotifyPropertyChanged<TProperty>(Expression<Func<TProperty>> property)
        {
            if (property == null || this.PropertyChanged == null)
            {
                return;
            }

            try
            {
                if (property.Body is MemberExpression)
                {
                    var body = property.Body as MemberExpression;
                    this.PropertyChanged(this, new PropertyChangedEventArgs(body.Member.Name));
                }
            }
            catch (Exception ex)
            {
                this.log.Write(
                    string.Format(
                    CultureInfo.InvariantCulture,
                    "Unable to fire command PropertyChanged on {1}, with exception {0}: ",
                    ex.Message,
                    this.GetType().FullName));
                throw;
            }
        }
    }
}
